home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 4
/
Apprentice-Release4.iso
/
Languages
/
CGI shell
/
cgishell.4th
< prev
next >
Wrap
Text File
|
1995-09-27
|
10KB
|
292 lines
\
\
\ PF Forms Handler Shell -- version 1.2
\
\
\ (c) Ronald T. Kneusel, 1995
\ (rkneusel@post.its.mcw.edu)
\
\ This code may be used and distributed freely provided the copyright
\ notice remains intact and my name is mentioned in the documentation.
\
\ Last mod: 27-Sep-95
\ =========================================================================
\
\ Provides a shell for writing CGI applications for use with WebSTAR. The
\ shell will handle all communication between WebSTAR and the CGI. It also
\ provides a vocabulary for extracting the information presented by WebSTAR.
\
\
\ @Field ( addr1 addr2 new|append -- )
\
\ Get the post data string for the field whose address is
\ on the stack. Place the data into the string at addr2. @Field
\ will convert characters as necessary.
\
\ @Addr ( addr new|append -- )
\
\ Put the client's IP address in the string at addr
\
\ @Direct ( addr new|append -- )
\
\ Put the direct argument in the string at addr
\
\ @Browser ( addr new|append -- )
\
\ Put the browser type in the string at addr
\
\ REPLY ( addr -- )
\
\ Send the string back to WebSTAR. Use only within ae: ... ;ae
\
( *************************** String Functions **************************** )
: MESSAGE[ \ compiling: ( -- ) enclose subsequent ']'ed string
CREATE 93 word here c@ 1+ dup 2 mod + allot 0 [compile] ,
DOES> count drop ; \ runtime action: ( -- addr )
: STRING>> \ compiling: ( n -- ) number of bytes in the string
CREATE allot ;
: <> = 0= ; macro
: newstr ( addr -- ) \ zero a string
0 swap c! ;
: length ( addr -- count ) \ length of the string at addr
dup >r BEGIN dup c@ 0 <> WHILE 1+ REPEAT r> - ;
: strcpy ( str1 str2 -- ) \ copy string 1 to string 2
dup length + >r \ automatically append
BEGIN dup c@ 0 <> WHILE
dup c@ r c! r> 1+ >r 1+
REPEAT 0 r> c! ;
: strncpy ( str1 str2 -- ) \ copy as above, clear str2 first
dup newstr strcpy ;
: 0type ( addr -- ) \ type null terminated string
dup length dup 0 <> IF type ELSE 2drop THEN ;
: >null ( addr -- ) \ convert a counted string into a null terminated string
dup c@ 2dup + >r swap dup 1+ swap rot cmove 0 r> c! ;
: >count ( addr -- ) \ convert a null terminated string into a counted string
dup length >r dup dup 1+ r cmove r> swap c! ;
: accept ( addr len -- ) \ like expect but no blank at end of line
swap dup >r swap expect 0 r r> length 1- c! ;
( **************** Apple Event and reply string handler ******************* )
\ This code courtesy of C. Heilman
2variable DDATA 4 allot
MESSAGE[ SERROR Empty stack!]
( get AEDesc handle from an Apple Event )
: ?DESC ( d.key d.type -- desc.handle desc.type -1 or 0 )
0 >r ( room for error )
202 +md 2@ 2>r ( the AppleEvent handle )
2swap 2>r 2>r ( keyword and type )
here a>r ( receiving address )
,$ 303C ,$ 812 ,$ A816 ( AEGetParamDesc: move #$812,d0 _Pack8 )
r> 0= IF ( if there is no error )
here 4 + 2@ here 2@ -1 ( get data & leave true )
ELSE 0 THEN ; ( or else leave false )
: -DESC ( addr.where.desc.is.stored -- error ) ( remove desc rec. )
0 >r a>r ( push room and descriptor )
,$ 303C ,$ 0204 ,$ A816 ( AEDisposeDesc: move #$0204,d0 _Pack8 )
r> ;
2variable DSIZE \ this double variable holds the size of a string in dbuff
variable DBUFF 2046 allot \ this block is filled with a text string
( get AE data from an Apple Event )
: ?DATA ( d.key -- addr length -1 or 0 )
0 >r \ make room on stack for error
202 +md 2@ 2>r \ push theAppleEvent address
2>r ,s TEXT 2>r \ push keyword (from pstack) and desired type (TEXT)
here a>r \ push an address to hold the actual type
dbuff a>r \ push the data receiving address
2048 s>d 2>r \ max number of bytes to read
dsize a>r \ push a variable to hold the actual size
,$ 303C ,$ 0E11 ,$ A816 \ AEGetParamPtr: move #$812,d0 _Pack8
r> 0= IF \ if there is no error
dbuff dsize 2@ drop -1 \ put address, count and true on pstack
ELSE 0 THEN ; \ else false
\ Reply to an Apple Event with a string
: REPLY ( addr -- ) \ **** USE INSIDE OF A HANDLER ONLY ****
dup length \ how long is it?
0 >r \ put room for error on rstack
198 +md 2@ 2>r \ put the ReplyEvent handle on rstack
,s ---- 2>r ,s TEXT 2>r \ put keyword and type on rstack
swap a>r 0 2>r \ put addr & count on rs from pstack
,$ 303C ,$ 0A0F ,$ A816 \ AEPutParamPtr: move #$A0F,d0 _Pack8
r> drop ; \ ignore any error
( ******************* Words to get field data *********************** )
0 constant NEW \ start a new string
-1 constant APPEND \ append at end of existing string
variable theAddr \ holds the address of the string
: zeroStr ( -- ) \ zero the string in theAddr
0 theAddr @ c! ;
: >append ( c -- ) \ put a character on the end of theAddr
theAddr @ length theAddr @ + dup >r c! \ character
0 r> 1+ c! ; \ null
: count>str ( addr len -- ) \ copy characters into the string
>r dup r> + swap DO
r c@ >append
LOOP ;
: h>d ( c -- d ) \ hex digit to decimal, no error checking
dup 64 > IF 55 - ELSE 48 - THEN ;
: hex>char ( addr -- addr+2 ) \ convert a %xx sequence into a character
1+ dup c@ swap 1+ dup c@ swap >r ( save addr )
h>d swap h>d 16 * +
dup 32 < IF
13 = IF 13 >append THEN \ return character
ELSE
>append \ anything >= space
THEN
r> ; ( pull address )
variable <end> \ where to stop
: count>str+ ( addr len -- ) \ copy characters into the string (filtered)
swap dup rot + <end> !
BEGIN
dup <end> @ < \ not at the end of the string
WHILE
dup c@
dup 43 = IF drop 32 >append ELSE \ pluses to spaces
dup 37 = IF drop ( a) hex>char ELSE \ non-alphanumeric character
>append THEN THEN \ alphanumeric character
1+ \ move to next character
REPEAT ;
create ~cr 3 allot 13 ~cr c! 10 ~cr 1+ c! 0 ~cr 2+ c!
: +crlf ~cr swap strcpy ; \ add a <cr><lf> pair
message[ ~#1 <html>]
message[ ~#2 </html>]
: startString ( addr -- ) ( load the header text into string )
~#1 swap strcpy ;
: endString ( addr -- ) ~#2 swap strcpy ; ( ending text )
( *************************** Number <--> String ************************* )
: f>str ( f addr -- ) \ convert a float to a string in addr
depth 4 > IF \ original CH, modified by RTK
theAddr ! zeroStr \ dest address
@pen 2>r 10 +md @ >r 30000 10 +md ! \ move pen offscreen
3000 3000 !pen f. \ print float: string is at here
r> 10 +md ! 2r> !pen \ return pen to origonal position
here count count>str \ put it addr
ELSE serror THEN ;
: str>f ( addr -- f ) \ convert a string into a float
1- >abs fnumber ;
( ********************** User level words ************************* )
: @Direct ( addr new|append -- ) \ get the direct argument
swap theAddr ! \ store the string address
NEW = IF zeroStr THEN \ clear the string
,s ---- ?data IF count>str THEN \ get the argument
;
: @Addr ( addr new|append -- ) \ get the IP address
swap theAddr ! \ store the string address
NEW = IF zeroStr THEN \ clear the string
,s addr ?data IF count>str THEN \ get it
;
: @Browser ( addr new|append -- ) \ get the browser type
swap theAddr ! \ store string address
NEW = IF zeroStr THEN
,s Agnt ?data IF count>str THEN \ get it
;
\
\ Fetch Field Data
\
variable fname \ holds field name address
variable postend \ holds end of post data address
: [@] ( a offset -- v ) + c@ ;
variable sflg
: same? ( str1 str2 -- t|f ) \ true if str1==str2, length from str2
-1 sflg !
dup length 0 DO 2dup
r [@] swap r [@]
<> IF 0 sflg ! leave THEN
LOOP 2drop
sflg @ ;
: nextField ( indx -- indx' eos? ) \ move pointer to the next field name
\ i.e. advance to 1 beyond next '&' character
BEGIN
dup dup c@ 38 <>
swap postend @ <> and \ while not '&' and not at end of string
WHILE 1+
REPEAT
dup c@ 0= IF -1 ELSE 1+ 0 THEN
;
: fData ( addr -- addr' ) \ return pointer to beginning of field data
BEGIN
dup dup c@ 61 <> \ while not an '='
swap postend @ <> and \ and not end-of-data
WHILE 1+ \ move to next char
REPEAT
1+ \ really want to end up pointing just beyond the '='
;
: fLen ( addr -- len ) \ return length of field data
dup BEGIN
dup dup c@ 38 <> \ while not an '&'
swap postend @ <> and \ and not end-of-data
WHILE 1+ \ move to next char
REPEAT
swap - \ return the length
;
: @Field ( addr1 addr2 new|append -- ) \ get the data for a field
rot theAddr !
NEW = IF zeroStr THEN
fname ! \ address of field name string
,s post ?data IF \ there is post data
postend ! \ store the length
dup postend +! \ and find end of post data address
( a ) 0 \ start of string, eos? flag
BEGIN 0=
WHILE
dup fname @ same? \ right field?
IF
fData dup fLen \ yes, move to field data and get length
count>str+ \ then copy to the output string
-1 \ flag end of loop
ELSE
nextField \ no, move to next
THEN
REPEAT
drop \ remove addr
THEN
;